package bean.factorybean;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author com.alibaba.lizhen
 * @Date 2021/3/30 11:42 上午
 * @Version 1.0
 * @Description
 */
public class TestBeanFactoryFactoryBean {
	public static void main(String[] args) {
		//这个是BeanFactory
		BeanFactory beanFactory =
//				new ClassPathXmlApplicationContext("bean.factorybean/config.xml");
		        new AnnotationConfigApplicationContext(Config.class);
		//获取对应的对象化
		Person person = (Person) beanFactory.getBean("person");
		System.out.println(person);
		/**
		 *TODO
		 *   当spring ioc初始化bean时，判断如果是FactoryBean，则会把该类注入到spring ioc。
		 *   1、当从BeanFactory中拿该FactoryBean时，用的是 &factoryBean，即beanFactory.getObj(&factoryBean)
		 *   2、如果想获取FactoryBean产生的泛型对象T，调用beanFactory.getObj(factoryBean)，
		 *      底层最终调用{@link FactoryBean#getObject()}。
		 *      2.1 如果T对象不是单利，则每次都是从{@link FactoryBean#getObject()}获取
		 *      2.2 如果T对象是单利，在第一次创建T对象后，
		 *         会放入到{@link FactoryBeanRegistrySupport#earlySingletonObjects}的cache中。
		 *         FactoryBeanRegistrySupport是 BeanFactory实现类  的父类。
		 *   需要注意的是：
		 *     当IOC存放FactoryBean是，name是factoryBean,前面的&符，不会放入到IOC。
		 *     获取的时候，见{@link AbstractAutowireCapableBeanFactory#doGetBean(String, Class, Object[], boolean)}
		 */
		//获取从FactoryBean中获取对象
		Person personFromFactory = beanFactory.getBean("personFactoryBean", Person.class);
		System.out.println(personFromFactory);
		Person personFromFactory2 = beanFactory.getBean("personFactoryBean", Person.class);
		System.out.println(personFromFactory2);
		System.out.println("(personFromFactory == personFromFactory2) = " + (personFromFactory == personFromFactory2));
		//获取对应的personFactory
		Object factoryBean = beanFactory.getBean("&personFactoryBean");
		System.out.println(factoryBean instanceof PersonFactoryBean);
		System.out.println("FactoryBean = " + factoryBean);
	}
}
